package cn.thoughtworks.school.visualization.service;

import cn.thoughtworks.school.visualization.Constant;
import cn.thoughtworks.school.visualization.entity.CacheReport;
import cn.thoughtworks.school.visualization.entity.Query;
import cn.thoughtworks.school.visualization.repositories.QueryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class QueryService {
    @Autowired
    private RedashService redashService;
    @Autowired
    private QueryRepository queryRepository;

    private CacheReport findByTypeAndProgramId(String type, Long programId, Long tutorId, String sql, boolean fromCache) {
        Query query = generateQuery(type, programId, sql);
        query.replaceTutorId(tutorId);
        return fromCache
            ? redashService.findQueryResult(query, programId, tutorId, type)
            : redashService.queryResult(query, programId, tutorId, type);
    }

    private Query generateQuery(String type, Long programId, String sql) {
        type = type + "-" + programId;
        Query query = queryRepository.findByProgramIdAndType(programId, type);
        if (Objects.isNull(query)) {
            Map data = redashService.creteQuery(type, sql);
            query = queryRepository.save(Query.build(programId, type, data.get("id").toString(), sql));
        }
        return query;
    }


    public CacheReport findAssignmentsStudentsStatus(Long programId, Long tutorId, String type, boolean fromCache) {
        String sql = Constant.getSQL(type).replace("PROGRAM_ID", programId + "");

        return findByTypeAndProgramId(type, programId, tutorId, sql, fromCache);
    }

    public List<Map<String, String>> findAssignmentsStudentsStatusData(Long programId, Long tutorId, String type, boolean fromCache){
        return findAssignmentsStudentsStatus(programId, tutorId, type, fromCache).getData();
    }

    public CacheReport findAssignmentsStudentsStatusByAssignment(Long programId, Long assignmentId, Long tutorId, String type, boolean fromCache) {
        String sql = Constant.getSQL(type).replace("PROGRAM_ID", programId + "");

        return findByTypeAndProgramIdAndAssignmentId(type, programId, assignmentId, tutorId, sql, fromCache);
    }

    private CacheReport findByTypeAndProgramIdAndAssignmentId(String type, Long programId, Long assignmentId, Long tutorId, String sql, boolean fromCache) {
        Query query = generateQuery(type, programId, sql);
        query.replaceTutorId(tutorId);
        query.replaceAssignmentId(assignmentId);

        return fromCache
            ? redashService.findQueryResult(query, programId, tutorId, type)
            : redashService.queryResult(query, programId, tutorId, type);
    }

    public CacheReport findAssignmentsStudentsStatusByTag(Long programId, Long tagId, Long assignmentId, Long tutorId, String type, boolean fromCache) {
        String sql = Constant.getSQL(type).replace("PROGRAM_ID", programId + "");

        return findByTypeAndProgramIdAndAssignmentIdAndTagId(type, programId, tagId, assignmentId, tutorId, sql, fromCache);
    }

    private CacheReport findByTypeAndProgramIdAndAssignmentIdAndTagId(String type, Long programId, Long tagId, Long assignmentId, Long tutorId, String sql, boolean fromCache) {
        Query query = generateQuery(type, programId, sql);
        query.replaceTutorId(tutorId);
        query.replaceAssignmentId(assignmentId);
        query.replaceTagId(tagId);

        return fromCache
            ? redashService.findQueryResult(query, programId, tutorId, type)
            : redashService.queryResult(query, programId, tutorId, type);
    }

}
